package com.itlong.cloud.controller.mine;


import com.itlong.cloud.POJO.PO.PropertyRolePO;
import com.itlong.cloud.POJO.PO.PropertyUserInfoPO;
import com.itlong.cloud.POJO.PO.UserLoginLogPO;
import com.itlong.cloud.POJO.VO.MessageVO;
import com.itlong.cloud.POJO.VO.app.property.app.PropertyAppUserProjectInfoVO;
import com.itlong.cloud.POJO.VO.property.PropertyUserCacheVO;
import com.itlong.cloud.PlatformConstants;
import com.itlong.cloud.abstracts.BaseController;
import com.itlong.cloud.annotation.LoggerInfo;
import com.itlong.cloud.constants.RedisConstant;
import com.itlong.cloud.enumerate.DataStatusEnum;
import com.itlong.cloud.enumerate.LanguageTypeEnum;
import com.itlong.cloud.enumerate.SystemTypeEnum;
import com.itlong.cloud.enumerate.ecode.*;
import com.itlong.cloud.enumerate.ecode_en.AppErrorCodeEnumEN;
import com.itlong.cloud.enumerate.ecode_en.BaseErrorCodeEnumEN;
import com.itlong.cloud.iottp.IIotTpSmsServiceClient;
import com.itlong.cloud.service.RedisService;
import com.itlong.cloud.thrown.DataAccessException;
import com.itlong.cloud.user.propertyapp.IPropertyAppUserInfoServiceClient;
import com.itlong.cloud.utils.encrypt.Md5;
import com.itlong.cloud.utils.encrypt.UserTokenUtil;
import com.itlong.cloud.utils.network.http.HttpProtocolUtil;
import com.itlong.cloud.utils.words.NumberHandlerUtil;
import com.itlong.cloud.utils.words.StringHandlerUtil;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <desc>
 * 物业app我的-登陆控制器
 * </desc>
 *
 * @createDate 2019/12/30
 */
@RestController
@RequestMapping("/user")
@RefreshScope
public class PropertyAppLoginController extends BaseController {

    private static Logger LOG = LoggerFactory.getLogger(PropertyAppLoginController.class);

    @Value("${" + PlatformConstants.PROPERTY_APP_MD5_ENCRYPT_KEY + "}")
    private String PROPERTY_APP_MD5_ENCRYPT_KEY;
    @Value("${" + PlatformConstants.PROPERTY_APP_USER_TOKEN_KEY + "}")
    private String PROPERTY_APP_USER_TOKEN_KEY;

    @Autowired
    private IPropertyAppUserInfoServiceClient propertyAppUserInfoServiceClient;

    @Autowired
    private IIotTpSmsServiceClient iIotTpSmsServiceClient;

    @Autowired
    private RedisService<PropertyUserCacheVO> redisService;

    private String userIdSeparator = "_";

    /**
     * <desc>
     * 物业app登录
     * </desc>
     *
     * @param accountNo   账号
     * @param password    密码
     * @param uuid
     * @param loginDevice 登录设备
     * @param createTime  创建时间
     * @param language    语言
     * @return
     * @Author Zhu.yj
     * @createDate 2019/12/31
     */
    @ResponseBody
    @LoggerInfo(identifer = "login")
    @RequestMapping(value = "/login", method = RequestMethod.POST)
    public Object login(String accountNo, String password, String uuid, String loginDevice, String createTime, String language) {
        try {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            accountNo = request.getAttribute("accountNo") == null ? null : request.getAttribute("accountNo").toString();
            password = request.getAttribute("password") == null ? null : request.getAttribute("password").toString();
            uuid = request.getAttribute("uuid") == null ? null : request.getAttribute("uuid").toString();
            loginDevice = request.getAttribute("loginDevice") == null ? null : request.getAttribute("loginDevice").toString();
            language = request.getAttribute("language") == null ? null : request.getAttribute("language").toString();
            createTime = request.getAttribute("createTime") == null ? null : request.getAttribute("createTime").toString();
            //验签在参数加解密拦截器中执行
            if (StringUtils.isBlank(accountNo) || StringUtils.isBlank(password)) {
                if (LanguageTypeEnum.CHINESE.getLanguage().equals(language)) {
                    return new MessageVO(AppErrorCodeEnum.PHONE_PSWD_EMPTY.getErrorCode());
                }
                return new MessageVO(AppErrorCodeEnumEN.PHONE_PSWD_EMPTY.getErrorCode());
            }
            if (StringUtils.isBlank(createTime) || StringUtils.isBlank(loginDevice) || StringUtils.isBlank(uuid)) {
                if (LanguageTypeEnum.CHINESE.getLanguage().equals(language)) {
                    return new MessageVO(BaseErrorCodeEnum.NOT_PARAM.getErrorCode());
                }
                return new MessageVO(BaseErrorCodeEnumEN.NOT_PARAM.getErrorCode());
            }
            String passwordStr = UserTokenUtil.getPassword(password, PROPERTY_APP_USER_TOKEN_KEY);
            if (StringUtils.isBlank(passwordStr)) {
                return new MessageVO(AppErrorCodeEnum.PUB_LOGIN_PARAMS_IS_EMPTY.getErrorCode());
            }
            //检查账号是否被锁定
            MessageVO checkLockMessage = propertyAppUserInfoServiceClient.getPropertyAppAccountLockDetail(accountNo);
            if (checkLockMessage != null){
                return checkLockMessage;
            }
            Map<String, Object> searchParams = new HashMap<>();
            searchParams.put("accountNo", accountNo);
            searchParams.put("password", Md5.En(passwordStr));
            PropertyUserInfoPO propertyUserInfoPO = propertyAppUserInfoServiceClient.getPropertyUserInfo(searchParams);
            if (propertyUserInfoPO == null || propertyUserInfoPO.getUserId() == null) {
                MessageVO checkMessage = propertyAppUserInfoServiceClient.propertyAppLoginErrorHandler(accountNo);
                return checkMessage;
            }
            //是否被禁用
            if (propertyUserInfoPO.getStatus() == DataStatusEnum.BAN.getType()) {
                return new MessageVO(AppErrorCodeEnum.USER_ACCOUNT_REFUSE.getErrorCode());
            }
            UserLoginLogPO userLoginLogPO =new UserLoginLogPO(accountNo,propertyUserInfoPO.getRealName(),HttpProtocolUtil.getIpAddr(request));
            if (loginDevice.equals("2")){
                userLoginLogPO.setSystemType(4);
            }else {
                userLoginLogPO.setSystemType(3);
            }
            //该账号是否绑定手机号
            if (StringUtils.isBlank(propertyUserInfoPO.getAdministratorPhone())){
                return new MessageVO(PropertyAppErrorCodeEnum.ACCOUNT_NOT_BIND_PHONE.getErrorCode());
            }
            //判断角色是否被禁用
            List<PropertyRolePO> propertyRolePOList = propertyAppUserInfoServiceClient.getPubTypeByRole(propertyUserInfoPO.getRoleId());
            if (propertyRolePOList.size() == 0){
                return new MessageVO(PropertyAppErrorCodeEnum.ACCOUNT_ROLE_NOT_EXIST.getErrorCode());
            }
            boolean loginFlag = false;
            for (PropertyRolePO propertyRolePO : propertyRolePOList){
                if (propertyRolePO.getStatus() == DataStatusEnum.NORMAL.getType() && propertyRolePO.getPropertyApp() ==1){
                    loginFlag = true;
                    break;
                }
            }
            //判断角色是否为单角色且角色为4独立开发者或6一卡通开发者
            if ("4".equals(propertyRolePOList.get(0).getRoleId())
                    || "6".equals(propertyRolePOList.get(0).getRoleId())){
                return new MessageVO(PropertyAppErrorCodeEnum.PROJECT_ROLE_FORBIDDEN.getErrorCode());
            }
            if (!loginFlag){
                return new MessageVO(PropertyAppErrorCodeEnum.ACCOUNT_ROLE_IS_FORBIDDEN_OR_AUTH_CLOSED.getErrorCode());
            }

            List<PropertyAppUserProjectInfoVO> projectMapList = propertyAppUserInfoServiceClient.getProjectListByUserId(propertyUserInfoPO.getUserId());
            //判断账号下项目状态
            if (projectMapList.size() == 0) {
                return new MessageVO(PropertyErrorCodeEnum.PUB_LOGIN_PROJECT_STATUS_IS_UNABLE.getErrorCode());
            } else {
                boolean flag = false;
                for (PropertyAppUserProjectInfoVO propertyAppUserProjectInfoVO : projectMapList) {
                    if (propertyAppUserProjectInfoVO.getStatus().equals("1")) {
                        flag = true;
                        break;
                    }
                }
                if (!flag) {
                    return new MessageVO(PropertyAppErrorCodeEnum.PROJECT_IS_FORBIDDEN.getErrorCode());
                }
            }
            Map<String, Object> resultMap = propertyAppUserInfoServiceClient.loginCacheUser(propertyUserInfoPO,loginDevice);
            if (resultMap != null) {
                userLoginLogPO.setDescription("登录成功");
                request.setAttribute("loginUser",userLoginLogPO);
                return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode(), resultMap);
            }
            throw new DataAccessException("【物业app-我的-物业app登录login】用户信息缓存失败");
        } catch (Exception e) {
            throw new DataAccessException("【物业app-我的-物业app登录login】物业app登录失败", e);
        }
    }


    /**
     * <desc>
     *      物业app找回密码
     * </desc>
     *
     * @param phoneNo    电话号码
     * @param pswd       密码
     * @param smsCode    验证码
     * @param createTime
     * @param sign
     * @param language
     * @return
     * @Author Zhu.yj
     * @createDate 2019/12/31
     */
    @ResponseBody
    @RequestMapping("/updatePswd")
    public Object updatePswd(String phoneNo, String pswd, String smsCode, String createTime, String sign, String language, String token) {
        try {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            phoneNo = request.getAttribute("phoneNo") == null ? null : request.getAttribute("phoneNo").toString();
            pswd = request.getAttribute("pswd") == null ? null : request.getAttribute("pswd").toString();
            smsCode = request.getAttribute("smsCode") == null ? null : request.getAttribute("smsCode").toString();
            createTime = request.getAttribute("createTime") == null ? null : request.getAttribute("createTime").toString();
            token = request.getAttribute("token") == null ? null : request.getAttribute("token").toString();
            language = request.getAttribute("language") == null ? null : request.getAttribute("language").toString();

            if (StringUtils.isBlank(phoneNo) || StringUtils.isBlank(pswd) || StringUtils.isBlank(smsCode) || StringUtils.isBlank(createTime)) {
                return new MessageVO(BaseErrorCodeEnum.PARAM_ERR.getErrorCode());
            } else if ((!NumberHandlerUtil.isPhoneNo(phoneNo))) {
                return new MessageVO(PropertyAppErrorCodeEnum.PHONE_NOT_MATCH.getErrorCode());
            } else if (StringUtils.isBlank(pswd) || pswd.length() < 6 || pswd.length() > 16) {
                return new MessageVO(AppErrorCodeEnum.PSWD_LENGTH_ERROR.getErrorCode());
            }
            //密码解密
            String password = UserTokenUtil.getPassword(pswd, PROPERTY_APP_USER_TOKEN_KEY);
            if (password == null) {
                return new MessageVO(AppErrorCodeEnum.PUB_LOGIN_PARAMS_IS_EMPTY.getErrorCode());
            }
            //
            String smsCodeCache = redisService.get(RedisConstant.REDIS_SMS_CODE + phoneNo);
            if (StringUtils.isBlank(smsCodeCache)) {
                return new MessageVO(AppErrorCodeEnum.SMSCODE_EXPIRE.getErrorCode());
            } else if (StringUtils.isNotBlank(smsCodeCache) && !smsCodeCache.equals(smsCode)) {
                return new MessageVO(AppErrorCodeEnum.SMSCODE_ERR.getErrorCode());
            } else if (StringUtils.isNotBlank(smsCodeCache) && smsCodeCache.equals(smsCode)) {
                //解密userid
                String userId = UserTokenUtil.newAPPTokenDecrypt(token, PROPERTY_APP_USER_TOKEN_KEY);
                //更新密码
                Map<String, Object> params = new HashMap<>();
                params.put("userId", userId);
                params.put("password", Md5.En(password));
                Integer result = propertyAppUserInfoServiceClient.updatePropertyUserPassword(params);
                //清除验证码缓存
                if (result > 0) {
                    redisService.del(RedisConstant.REDIS_SMS_CODE + phoneNo);//业务成功后移除验证码缓存
                    return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode());
                }
            }
            return new MessageVO(AppErrorCodeEnum.SMSCODE_ERR.getErrorCode());
        } catch (Exception e) {
            throw new DataAccessException("【物业APP-我的-找回密码updatePswd】物业app找回密码失败", e);
        }
    }

    /**
     * <desc>
     * 修改密码时发送验证码
     * </desc>
     *
     * @param phoneNo    电话号码
     * @param createTime 创建时间
     * @param sign       参数签名
     * @param language   语言
     * @param type      0手机 1邮箱
     * @return
     * @Author Zhu.yj
     * @createDate 2019/12/31
     */
    @ResponseBody
    @RequestMapping(value = "/sendMsg", method = RequestMethod.POST)
    public Object sendMsg(String phoneNo,String mode,String type, String createTime, String sign, String language) {
        try {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            phoneNo = request.getAttribute("phoneNo") == null ? null : request.getAttribute("phoneNo").toString();
            createTime = request.getAttribute("createTime") == null ? null : request.getAttribute("createTime").toString();
            //type暂只支持手机号登录，所以先不做处理
            type = request.getAttribute("type") == null ? null : request.getAttribute("type").toString();
            mode = request.getAttribute("mode") == null ? null : request.getAttribute("mode").toString();
            if (StringUtils.isEmpty(phoneNo) || StringUtils.isBlank(createTime) || StringUtils.isBlank(mode) || StringUtils.isBlank(type)) {
                return new MessageVO(BaseErrorCodeEnum.NOT_PARAM.getErrorCode());
            }
            String smsCode = NumberHandlerUtil.randomNum(6);
            boolean sendFlag = false;  //验证码发送标志,true-发送成功，false-发送失败
            String content = "验证码:" + smsCode + ",该验证码将在30分钟后失效.";
            if ("0".equals(type) && !NumberHandlerUtil.isPhoneNo(phoneNo)) { //手机号是否合法
                return new MessageVO(AppErrorCodeEnum.PHONE_NOT_MATCH.getErrorCode());
            }
            PropertyUserInfoPO propertyUserInfoPO = propertyAppUserInfoServiceClient.getByAccount(phoneNo);
            //需求10分钟之内可以发送3条
            //按顺序放入缓存3条如果都存在则报错,每条10分钟超时
            int count1 = redisService.get(RedisConstant.REDIS_SMS_TIMES + "1" + phoneNo) == null ? 0 : 1;
            int count2 = redisService.get(RedisConstant.REDIS_SMS_TIMES + "2" + phoneNo) == null ? 0 : 1;
            int count3 = redisService.get(RedisConstant.REDIS_SMS_TIMES + "3" + phoneNo) == null ? 0 : 1;
            if (count1 != 0 && count2 != 0 && count3 != 0) {//都不为空证明已经发了3次
                return new MessageVO(AppErrorCodeEnum.SMSCODE_SEND_TO_MORE.getErrorCode());
            }
            if (count1 == 0) {
                redisService.set(RedisConstant.REDIS_SMS_TIMES + "1" + phoneNo, RedisConstant.SMS_TIMES_TIME, "1");
            } else if (count2 == 0) {
                redisService.set(RedisConstant.REDIS_SMS_TIMES + "2" + phoneNo, RedisConstant.SMS_TIMES_TIME, "1");
            } else if (count3 == 0) {
                redisService.set(RedisConstant.REDIS_SMS_TIMES + "3" + phoneNo, RedisConstant.SMS_TIMES_TIME, "1");
            }
            sendFlag = iIotTpSmsServiceClient.sendSmsCodeByPhone(phoneNo, content);
            if (sendFlag) {
                boolean redisFlag = false;
                redisFlag = redisService.set(RedisConstant.REDIS_SMS_CODE + phoneNo, RedisConstant.SMS_CODE_TIME, smsCode);
                if (redisFlag) {
                    return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode());
                } else {
                    LOG.info("【物业APP_我的_获取验证码缓存验证码失败】");
                    return new MessageVO(AppErrorCodeEnum.SMSCODE_SEND_ERR.getErrorCode());
                }
            }
            return new MessageVO(AppErrorCodeEnum.SMSCODE_SEND_ERR.getErrorCode());
        } catch (Exception e) {
            throw new DataAccessException("【物业APP-我的-发送验证码appSendSmsCode】发送验证码失败", e);
        }
    }

    /**
     * <desc>
     * 物业app退出登录
     * </desc>
     *
     * @param token 登录凭证
     * @return
     * @Author Zhu.yj
     * @createDate 2020/1/9
     */
    @ResponseBody
    @RequestMapping(value = "/loginOut", method = RequestMethod.POST)
    public Object loginOut(String token, HttpServletRequest request) {
        try {
            token = request.getAttribute("token") == null ? null : request.getAttribute("token").toString();
            String userId = UserTokenUtil.newAPPTokenDecrypt(token, PROPERTY_APP_USER_TOKEN_KEY);
            boolean flag = propertyAppUserInfoServiceClient.loginOut(userId);
            if (flag) {
                return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode());
            }
            LOG.info("【缓存用户信息失败】");
            return new MessageVO(BaseErrorCodeEnum.ERROR.getErrorCode());
        } catch (Exception e) {
            throw new DataAccessException("【物业APP-首页-退出登录logout】退出登录失败", e);
        }
    }

    /**
     * <desc>
     *     物业找回密码时验证验证码是否正确
     * </desc>
     * @param phoneNo 手机号
     * @param language 语言
     * @param smsCode  短信验证码
     * @return
     * @author Qiang.S
     * @createDate 2019-06-28
     *
     */
    @ResponseBody
    @RequestMapping(path = "/checkSmsForChangePhone",method = RequestMethod.POST)
    public Object checkSmsForChangePhone(String phoneNo,String smsCode,String createTime,String language) throws  Exception{
        try {
            boolean flag1 = StringUtils.isNotBlank(createTime);
            if (!flag1) {
                HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
                phoneNo = request.getAttribute("phoneNo") == null ? null : request.getAttribute("phoneNo").toString();
                smsCode = request.getAttribute("smsCode") == null ? null : request.getAttribute("smsCode").toString();
                createTime = request.getAttribute("createTime") == null ? null : request.getAttribute("createTime").toString();
                language = request.getAttribute("language") == null ? null : request.getAttribute("language").toString();
            }
            //校空
            if (StringUtils.isBlank(phoneNo)||StringUtils.isBlank(smsCode)||StringUtils.isBlank(createTime)){
                return new MessageVO(BaseErrorCodeEnum.NOT_PARAM.getErrorCode());
            }else if ((!NumberHandlerUtil.isPhoneNo(phoneNo))){
                return new MessageVO(AppErrorCodeEnum.PHONE_NOT_MATCH.getErrorCode());
            }
            String smsCodeCache = redisService.get(RedisConstant.REDIS_SMS_CODE+phoneNo);
            if (StringUtils.isBlank(smsCodeCache)){
                return new MessageVO(AppErrorCodeEnum.SMSCODE_EXPIRE.getErrorCode());
            }else if (StringUtils.isNotBlank(smsCodeCache)&&!smsCodeCache.equals(smsCode)){
                return new MessageVO(AppErrorCodeEnum.SMSCODE_ERR.getErrorCode());
            }else if (StringUtils.isNotBlank(smsCodeCache)&&smsCodeCache.equals(smsCode)){
//                    redisService.del(RedisConstant.REDIS_SMS_CODE+phoneNo); //业务成功后移除验证码缓存
                return  new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode());
            }else {
                return  new MessageVO(BaseErrorCodeEnum.ERROR.getErrorCode());
            }
        }catch (Exception e){
            LOG.error("【物业APP_验证手机验证码_验证码验证异常】",e);
            throw new DataAccessException("【APP_登录注册模块_验证码验证异常】验证码验证异常",e);
        }
    }


}